home *** CD-ROM | disk | FTP | other *** search
- /* BlizKick EXTRES allocation API functions.
-
- Written by Harry "Piru" Sintonen, Jan 2000.
- Public Domain.
-
- */
-
- #include "bkapi.h"
-
- #define __USE_SYSBASE 1
-
- #include <proto/exec.h>
- #include <proto/dos.h>
-
-
- /****** bkapi.o/--background-- ***********************************************
- *
- * PURPOSE
- * If you don't know what BlizKick is get util/boot/BlizKick.lha
- * from aminet and read the documentation of it.
- *
- * The BlizKick EXTRES buffer is a finite space where BlizKick stores
- * resident tags. This area is magically added to Kickstart ROM's
- * internal list of memory areas to scan for resident tags. As a
- * result BlizKick does not need to use unreliable exec.library
- * KickMem & KickPtr vectors.
- *
- * This package provides easy (as easy as it can get) access to this
- * BlizKick EXTRES buffer.
- *
- * First application to think of, would be ROM Update software that
- * could easily kick in new resident module by just calling
- * er_allocmem and copying resident tag to memory area returned. On
- * next reboot this new resident tag would be activated.
- *
- * To get things even easier, one can use InternalLoadSeg with
- * er_allocmem as allocfunc, er_free as freefunc and dos Read() as
- * readfunc. Then just LoadSeg any library / device to make it
- * resident. Relocs and such get handled autogically! (however most
- * disk based libraries would not survive, namely residenttag ln_Pri
- * is wrong.)
- *
- * Don't expect this API to stay unchanged. There will be some sort
- * of MMU protection for EXTRES buffer some day... I think. However
- * programs respecting ERH_API_V1 will probably recompile out of the
- * box in the future too.
- *
- * HISTORY
- * 1.0.1 - 17th Jan 2000, second release. fixed a typo.
- * 1.0.0 - 15th Jan 2000, first release.
- *
- * LEGAL
- * Written by Harry "Piru" Sintonen, Jan 2000.
- * bkapi package is public domain.
- *
- ******************************************************************************
- *
- */
-
- struct bkerhss *glob_ss = NULL;
-
-
- /*#define BKDEBUG*/
-
- #ifdef BKDEBUG
- # define D(a) (a);
- #else
- # define D(a) ;
- #endif
-
-
- /****** bkapi.o/er_init ******************************************************
- *
- * NAME
- * er_init -- initialize EXTRES buffer use
- *
- * SYNOPSIS
- * version = er_init()
- * D0
- *
- * ULONG er_init();
- *
- * FUNCTION
- * Initializes use of EXTRES buffer memory pool of BlizKick. This
- * routine must be called before using any of the other functions.
- *
- * RESULT
- * version - version number of EXTRES buf API available or zero
- * if EXTRES buf could not be found (ie. BlizKick not run).
- * Currently ERH_API_V1.
- *
- * SEE ALSO
- *
- ******************************************************************************
- *
- */
-
- ULONG er_init(void) {
- struct bkerhss *ss;
-
- if (!glob_ss) {
-
- Forbid();
- ss = (struct bkerhss *) FindSemaphore("EXTRES Handler");
- Permit();
-
- if (ss) {
-
- switch (ss->version) {
-
- case ERH_API_V1:
- glob_ss = ss;
- break;
-
- /*
- case ERH_API_V2:
- glob_ss = ss;
- ... could do some version dependant check / init here ...
- break;
- */
- }
-
- /* force sanity check */
- er_availmem(MEMF_LARGEST);
-
- }
- }
- return glob_ss ? glob_ss->version : 0;
- }
-
-
- /****** bkapi.o/er_alloc *****************************************************
- *
- * NAME
- * er_alloc -- allocate bytesize bytes from EXTRES memory pool
- *
- * SYNOPSIS
- * memoryblock = er_alloc(bytesize)
- * D0 D0
- *
- * void *er_alloc(ULONG);
- *
- * FUNCTION
- * Allocates memory from EXTRES buffer memory pool of BlizKick. This
- * memory area is specific in a way that resident tags will be scanned
- * from this area on system boot up.
- *
- * This means easy addition of system transparent resident tags.
- * System transparent means no kickmem or kicktag pointers will be
- * used.
- *
- * INPUTS
- * bytesize - the size of the desired block in bytes. (will
- * automatically round this number to a multiple of the
- * system memory chunk size)
- *
- * RESULT
- * memoryblock - a pointer to the newly allocated memory block.
- * If there are no free memory regions large enough to satisfy
- * the request, zero will be returned. The pointer must be
- * The memory block returned is quad word aligned.
- *
- * WARNING
- * The result of any memory allocation MUST be checked, and a viable
- * error handling path taken. ANY allocation may fail if memory has
- * been filled.
- *
- * NOTE
- * Allocation *will* fail if BlizKick is not run.
- *
- * SEE ALSO
- * er_allocmem, er_free, exec.library/Allocate
- *
- ******************************************************************************
- *
- */
-
- void * ASM er_alloc(REG(d0,ULONG bytesize)) {
- void *ret = NULL;
-
- if (glob_ss) {
-
- ObtainSemaphore(&glob_ss->ss);
- ret = Allocate(glob_ss->mh, bytesize);
- ReleaseSemaphore(&glob_ss->ss);
- }
-
- if (!ret) SetIoErr(ERROR_NO_FREE_STORE);
- return ret;
- }
-
-
- /****** bkapi.o/er_allocmem **************************************************
- *
- * NAME
- * er_allocmem -- AllocMem wrapper for er_alloc
- *
- * SYNOPSIS
- * memoryblock = er_allocmem(bytesize, attributes)
- * D0 D0 D1
- *
- * void *er_allocmem(ULONG, ULONG);
- *
- * FUNCTION
- * Allocates memory from EXTRES buffer memory pool of BlizKick. This
- * memory area is specific in a way that resident tags will be scanned
- * from this area on system boot up.
- *
- * This means easy addition of system transparent resident tags.
- * System transparent means no kickmem or kicktag pointers will be
- * used.
- *
- * This function is quite similar to er_alloc, the only difference
- * is that er_allocmem supports MEMF_CLEAR.
- *
- * If MEMF_CHIP is specified this function will fail.
- *
- * INPUTS
- * bytesize - the size of the desired block in bytes. (will
- * automatically round this number to a multiple of the
- * system memory chunk size)
- *
- * attributes -
- * requirements
- *
- * MEMF_CHIP: Will cause the allocation to fail. EXTRES
- * buffer memory is in fastmem.
- *
- * options
- *
- * MEMF_CLEAR: The memory will be initialized to all
- * zeros.
- *
- * RESULT
- * memoryBlock - a pointer to the newly allocated memory block.
- * If there are no free memory regions large enough to satisfy
- * the request, zero will be returned. The pointer must be
- * checked for zero before the memory block may be used!
- * The memory block returned is quad word aligned.
- *
- * WARNING
- * The result of any memory allocation MUST be checked, and a viable
- * error handling path taken. ANY allocation may fail if memory has
- * been filled.
- *
- * NOTE
- * Allocation *will* fail if BlizKick is not run.
- *
- * MEMF_CLEAR is the only flag supported! Other flags will be
- * silentry ignored, except MEMF_CHIP that will cause allocation to
- * fail.
- *
- * This function is provided for completeness and also for use as
- * dos.library/InternalLoadSeg() allocfunc.
- *
- * SEE ALSO
- * er_alloc, er_free, exec.library/AllocMem, exec/memory.h
- *
- ******************************************************************************
- *
- */
-
- void * __saveds ASM er_allocmem(REG(d0,ULONG bytesize), REG(d1,ULONG attributes)) {
- void *ret = NULL;
- ULONG *clearptr;
-
- if ( (bytesize==0) || (attributes & MEMF_CHIP) ) return NULL;
-
- if (glob_ss) {
-
- ObtainSemaphore(&glob_ss->ss);
-
- if ( (ret = Allocate(glob_ss->mh, bytesize)) ) {
-
- D(Printf("er_allocmem(%ld) = $%lx\n",
- bytesize,(ULONG) ret));
-
- /* actually the following could clear a bit too much, but it
- doesn't really matter. should clear only bytesize bytes. */
-
- if (attributes & MEMF_CLEAR) {
- clearptr = (ULONG *) ret;
- bytesize = (bytesize + MEM_BLOCKMASK) & -MEM_BLOCKSIZE;
-
- D(Printf("er_allocmem: clearing %ld bytes from $%lx\n",
- bytesize,(ULONG) clearptr));
-
- for ( ; bytesize; bytesize -= 8) {
- *clearptr++ = 0;
- *clearptr++ = 0;
- }
- }
- }
-
- ReleaseSemaphore(&glob_ss->ss);
- }
-
- if (!ret) SetIoErr(ERROR_NO_FREE_STORE);
-
- return ret;
- }
-
-
- /****** bkapi.o/er_free ******************************************************
- *
- * NAME
- * er_free -- deallocate memory from EXTRES memory pool
- *
- * SYNOPSIS
- * er_free(memoryblock, bytesize)
- * A1 D0
- *
- * void er_free(void *, ULONG);
- *
- * FUNCTION
- * Erase and free a region of memory, returning it to the EXTRES
- * memory pool.
- *
- * INPUTS
- * memoryblock - pointer to the memory block to free
- * bytesize - the size of the desired block in bytes. (will
- * automatically round this number to a multiple of the
- * system memory chunk size)
- *
- * NOTE
- * If a block of memory is freed twice, the system will Guru. The
- * Alert is AN_FreeTwice ($01000009). If you pass the wrong pointer,
- * you will probably see AN_MemCorrupt $01000005.
- *
- * Will also fill the memory area to be released with all ones
- * before releasing. This ensures no partial resident tag will
- * remain in unallocated memory.
- *
- * Both memory allocated by er_alloc and er_allocmem must be released
- * with this function!
- *
- * SEE ALSO
- * er_alloc, er_allocmem, exec.library/Allocate
- *
- ******************************************************************************
- *
- */
-
- void __saveds ASM er_free(REG(a1,void *memblock), REG(d0,ULONG bytesize)) {
- ULONG *fillptr; ULONG fillsize;
-
- if ( (bytesize==NULL) || (memblock==NULL) ) return;
-
- if (glob_ss) {
-
- /* actually the following could fill a bit too much, but it
- doesn't really matter. should fill only bytesize bytes. */
-
- fillptr = (ULONG *) ((ULONG)memblock & -MEM_BLOCKSIZE);
- fillsize = (bytesize + MEM_BLOCKMASK +
- ((ULONG) fillptr - (ULONG) memblock)) &
- -MEM_BLOCKSIZE;
-
- /* some sanity checking - note that doesn't require ObtainSemaphore
- because only mh_Lower and mh_Upper are read (both are static) */
-
- if ( ((ULONG) fillptr < (ULONG) glob_ss->mh->mh_Lower) ||
- (((ULONG)fillptr + fillsize) > (ULONG) glob_ss->mh->mh_Upper) ) {
-
- D(Printf("er_free: *** illegal arguments ***!\n"));
- return;
- }
-
- D(Printf("er_free, memblock: $%lx bytesize: %ld fillptr: $%lx fillsize: %ld\n",
- (ULONG) memblock, bytesize, (ULONG) fillptr, fillsize));
-
- ObtainSemaphore(&glob_ss->ss);
-
- for ( ; fillsize; fillsize -= 8) {
- *fillptr++ = 0xffffffff;
- *fillptr++ = 0xffffffff;
- }
-
- Deallocate(glob_ss->mh, memblock, bytesize);
- ReleaseSemaphore(&glob_ss->ss);
-
- }
- }
-
-
- /****** bkapi.o/er_allocvec **************************************************
- *
- * NAME
- * er_allocvec -- allocate EXTRES memory and keep track of the size
- *
- * SYNOPSIS
- * memoryblock = er_allocvec(bytesize, attributes)
- * D0 D0 D1
- *
- * void *er_allocvec(ULONG, ULONG);
- *
- * FUNCTION
- * This function works similar to er_allocmem(), but tracks the size
- * of the allocation.
- *
- * See the er_allocmem() documentation for details.
- *
- * RESULT
- * memoryBlock - a pointer to the newly allocated memory block.
- * If there are no free memory regions large enough to satisfy
- * the request, zero will be returned. The pointer must be
- * checked for zero before the memory block may be used!
- * The memory block returned is *long* word aligned.
- *
- * WARNING
- * The result of any memory allocation MUST be checked, and a viable
- * error handling path taken. ANY allocation may fail if memory has
- * been filled.
- *
- * SEE ALSO
- * er_allocmem, er_freevec, exec.library/AllocVec
- *
- ******************************************************************************
- *
- */
-
- void * ASM er_allocvec(REG(d0,ULONG bytesize), REG(d1,ULONG attributes)) {
- void *ret;
-
- bytesize += 4;
- if ( (ret = er_allocmem(bytesize, attributes)) ) {
- *(ULONG *)ret = bytesize;
- return (void *) ((ULONG) ret + 4);
- }
-
- return NULL;
- }
-
-
- /****** bkapi.o/er_freevec ***************************************************
- *
- * NAME
- * er_freevec -- free er_allocvec() EXTRES memory
- *
- * SYNOPSIS
- * er_freevec(memoryblock)
- * A1
- *
- * void er_freevec(void *);
- *
- * FUNCTION
- * Free an allocation made by the er_allocvec() call.
- *
- * NOTE
- * If a block of memory is freed twice, the system will Guru. The
- * Alert is AN_FreeTwice ($01000009). If you pass the wrong pointer,
- * you will probably see AN_MemCorrupt $01000005.
- *
- * INPUTS
- * memoryblock - pointer to the memory block to free, or NULL.
- *
- * SEE ALSO
- * er_allocvec, exec.library/FreeVec
- *
- ******************************************************************************
- *
- */
-
- void ASM er_freevec(REG(a1,void *memoryblock)) {
- ULONG size;
- if (memoryblock) {
- memoryblock = (void *) ((ULONG) memoryblock - 4);
- size = *((ULONG *) memoryblock);
- er_free( memoryblock, size);
- }
- }
-
-
- /****** bkapi.o/er_lock ******************************************************
- *
- * NAME
- * er_lock -- lock EXTRES buffer memory
- *
- * SYNOPSIS
- * er_lock()
- *
- * void er_lock(void);
- *
- * FUNCTION
- * Locks access to EXTRES buffer memory for this task only.
- *
- * WARNING
- * Be *very* careful not to keep the lock if another process you
- * depend/wait will try to er_lock() simultanously!
- *
- * NOTE
- * You *must* er_lock() before you read/write EXTRES buffer memory
- * area. Call er_unlock() when done tempering with it.
- *
- * er_lock() and er_unlock() nest.
- *
- * SEE ALSO
- * er_unlock, er_getarea
- *
- ******************************************************************************
- *
- */
-
- void ASM er_lock(void) {
- if (glob_ss) {
-
- ObtainSemaphore(&glob_ss->ss);
-
- }
- }
-
-
- /****** bkapi.o/er_unlock ****************************************************
- *
- * NAME
- * er_unlock -- unlock EXTRES buffer memory
- *
- * SYNOPSIS
- * er_unlock()
- *
- * void er_unlock(void);
- *
- * FUNCTION
- * Unlock access to EXTRES buffer memory. Other tasks may bid for
- * access now.
- *
- * WARNING
- * Be *very* careful not to keep the lock if another process you
- * depend/wait will try to er_lock() simultanously!
- *
- * NOTE
- * You *must* er_lock() before you read/write EXTRES buffer memory
- * area. Call er_unlock() when done tempering with it.
- *
- * er_lock() and er_unlock() nest.
- *
- * SEE ALSO
- * er_lock, er_getarea
- *
- ******************************************************************************
- *
- */
-
- void ASM er_unlock(void) {
- if (glob_ss) {
-
- ReleaseSemaphore(&glob_ss->ss);
-
- }
- }
-
-
- /****** bkapi.o/er_getarea ***************************************************
- *
- * NAME
- * er_getarea -- get EXTRES resident module area
- *
- * SYNOPSIS
- * start = er_getarea(len_ptr)
- * D0 A0
- *
- * void *er_getarea(ULONG *);
- *
- * FUNCTION
- * Return lower and upper bound of memory area covered by EXTRES
- * buffer.
- *
- * INPUTS
- * len_ptr - pointer to ULONG to put area lenght to.
- *
- * RESULT
- * start - pointer to start of resident module area. If there's no
- * BlizKick EXTRES buffer available will be zero.
- *
- * NOTE
- * You *must* er_lock() before you read/write EXTRES buffer memory
- * area. Call er_unlock() when done tempering with it.
- *
- * Will return zero if BlizKick is not run.
- *
- * SEE ALSO
- * er_lock, er_unlock
- *
- ******************************************************************************
- *
- */
-
- ULONG ASM er_getarea(REG(a0,ULONG *len_ptr)) {
- ULONG ret = NULL;
-
- if (glob_ss) {
- ObtainSemaphore(&glob_ss->ss);
-
- ret = (ULONG) glob_ss->mh->mh_Lower;
- *len_ptr = (ULONG) glob_ss->mh->mh_Upper - ret;
-
- ReleaseSemaphore(&glob_ss->ss);
- }
- return ret;
- }
-
-
- /****** bkapi.o/er_availmem **************************************************
- *
- * NAME
- * er_availmem -- return EXTRES buffer memory available
- *
- * SYNOPSIS
- * size = er_availmem(requirements)
- * D0 D1
- *
- * ULONG er_availmem(ULONG);
- *
- * FUNCTION
- * This function returns the amount of free EXTRES buffer memory.
- *
- * To find out what the largest block is, specify MEMF_LARGEST in
- * attributes argument.
- *
- * WARNING
- * Due to the effect of multitasking, the value returned may not
- * actually be the amount of free memory available at that instant.
- * However if you have locked memory with er_lock() before, the
- * result is exact.
- *
- * INPUTS
- * requirements - MEMF_LARGEST results calculation of the size of
- * the largest block.
- *
- * RESULT
- * size - total free space remaining (or the largest free block).
- *
- * NOTE
- * er_availmem(MEMF_LARGEST) does a consistency check on the
- * memory list. In case of an error 0xFFFFFFFF is returned, and
- * further allocations are impossible. If memory header itself is
- * bad will alert with BKA_MemoryInsane.
- *
- * SEE ALSO
- * exec.library/AvailMem, exec/memory.h
- *
- ******************************************************************************
- *
- */
-
- ULONG ASM er_availmem(REG(d1,ULONG attributes)) {
- struct MemHeader *mh;
- struct MemChunk *mc, *predmc;
- ULONG ret = NULL, free = 0, failed = 0;
-
- if (glob_ss) {
- ObtainSemaphore(&glob_ss->ss);
-
- if (attributes & MEMF_LARGEST) {
-
- mh = glob_ss->mh;
-
- if ( (mh->mh_Node.ln_Succ == NULL) &&
- (mh->mh_Node.ln_Pred == NULL) &&
- (mh->mh_Node.ln_Type == NT_MEMORY) &&
- (((ULONG) mh->mh_Lower & MEM_BLOCKMASK) == 0) &&
- (((ULONG) mh->mh_Upper & MEM_BLOCKMASK) == 0) &&
- (mh->mh_Lower < mh->mh_Upper)
- ) {
-
- mc = mh->mh_First;
- predmc = (struct MemChunk *) ((ULONG) mc - 1);
-
- while (mc && (!failed) ) {
- if ( ( ((ULONG) mc & MEM_BLOCKMASK) == 0) &&
- ((ULONG) mc > (ULONG) predmc) &&
- ((ULONG) mc <= ((ULONG) mh->mh_Upper - MEM_BLOCKSIZE))
- ) {
-
- if ( (mc->mc_Bytes & MEM_BLOCKMASK) == 0) {
-
- free += mc->mc_Bytes;
- if (mc->mc_Bytes > ret) ret = mc->mc_Bytes;
-
- } else failed = 1;
-
- predmc = mc;
- mc = mc->mc_Next;
-
- } else failed = 1;
-
- }
- } else {
- failed = 2;
- }
-
- if ( (!failed) && (free != mh->mh_Free) ) failed = 1;
-
- switch (failed) {
- case 2:
- /* memheader screwed up!! */
- D(Printf("er_availmem(largest): *** memheader fucked ***!!\n"));
- Alert(BKA_MemoryInsane);
- /* fall thru */
- case 1:
- D(Printf("er_availmem(largest): freelist fucked!\n"));
- mh->mh_First = NULL;
- mh->mh_Free = 0;
- ret = 0xFFFFFFFF;
- break;
- }
-
- } else {
- ret = glob_ss->mh->mh_Free;
- }
-
- ReleaseSemaphore(&glob_ss->ss);
- }
- return ret;
- }
-
- /****** bkapi.o/er_nextresident **********************************************
- *
- * NAME
- * er_nextresident -- find first/next resident tag from EXTRES buffer
- *
- * SYNOPSIS
- * nextresident = er_nextresident(oldresident)
- * D0 A0
- *
- * struct Resident *er_nextresident(struct Resident *);
- *
- * FUNCTION
- * Find first or next Resident tag from EXTRES buffer memory.
- *
- * WARNING
- * You *must* have er_lock() on memory before calling this routine!
- * Keep the lock until you're done accessing the resident tag(s).
- *
- * INPUTS
- * oldresident - startpoint for search, will not find this
- * particular resident but next. Pass NULL to find first
- * resident.
- *
- * RESULT
- * nextresident - pointer to resident tag structure or zero if no
- * more resident tags could be found.
- *
- * EXAMPLE
- *
- * struct Resident *res = NULL;
- *
- * er_lock();
- * while ( (res = er_nextresident(res)) ) {
- * \* do something with this Resident tag *\
- * }
- * er_unlock();
- *
- * SEE ALSO
- * er_findresident
- *
- ******************************************************************************
- *
- */
-
- struct Resident * ASM er_nextresident(REG(a0,struct Resident *oldresident)) {
- UWORD *wpt;
- LONG numw;
-
- if (glob_ss) {
-
- if (oldresident) {
-
- /* sanitycheck input */
-
- if ( ((ULONG) oldresident < (ULONG) glob_ss->mh->mh_Lower) ||
- (((ULONG) oldresident + sizeof(struct Resident)) >=
- (ULONG) glob_ss->mh->mh_Upper) ) {
- return NULL;
- }
-
- if ( (oldresident->rt_MatchWord == RTC_MATCHWORD) &&
- (oldresident->rt_MatchTag == oldresident) ) {
-
- wpt = (UWORD *) oldresident->rt_EndSkip;
-
- } else {
-
- wpt = (UWORD *) (((ULONG) oldresident + 3) & -2);
-
- }
-
- } else {
- wpt = (UWORD *) glob_ss->mh->mh_Lower;
- }
-
- /* more sanity checking */
-
- if ( ((ULONG) wpt < (ULONG) glob_ss->mh->mh_Lower) ||
- (((ULONG) wpt + sizeof(struct Resident)) >=
- (ULONG) glob_ss->mh->mh_Upper) ) {
- return NULL;
- }
-
- numw = (((ULONG) glob_ss->mh->mh_Upper
- - sizeof(struct Resident)
- - (ULONG) wpt) ) >> 1;
-
- if (numw > 0) {
- for ( ; ; ) {
- while (--numw && (*wpt++ != RTC_MATCHWORD));
- if (!numw) return NULL;
- if ( *(ULONG *) wpt == ((ULONG) wpt - 2) ) {
- return (struct Resident *) ((ULONG) wpt - 2);
- }
- }
- }
- }
-
- return NULL;
- }
-
-
- /****** bkapi.o/er_findresident **********************************************
- *
- * NAME
- * er_findresident -- find resident tag from EXTRES buffer by name
- *
- * SYNOPSIS
- * resident = er_findresident(name)
- * D0 A1
- *
- * struct Resident *er_findresident(STRPTR);
- *
- * FUNCTION
- * Scan EXTRES buffer memory for Resident tag with given name.
- *
- * WARNING
- * You must have er_lock() on memory before calling this routine
- * if you intend to access the resident tag found! Keep the lock
- * until you're done accessing the Resident tag.
- *
- * INPUTS
- * name - pointer to name string
- *
- * RESULT
- * resident - pointer to the resident tag structure or
- * zero if none found.
- *
- * EXAMPLE
- *
- * struct Resident *res = NULL;
- *
- * er_lock();
- * if (res = er_findresident("EXTRES Handler")) {
- * \* do something with the resident *\
- *
- * \* keep the lock until done! *\
- * }
- * er_unlock();
- *
- * NOTE
- * exec.library/FindResident() will only find the currently *active*
- * resident tags in EXTRES buffer memory. Also if resident tag with
- * same name is found from both the ROM and EXTRES memory, the one
- * having newer rt_Version will be activated on boot, and thus
- * exec.library/FindResident() will find that particular resident.
- *
- * SEE ALSO
- * er_nextresident, exec.library/FindResident, exec/resident.h
- *
- ******************************************************************************
- *
- */
-
- struct Resident * ASM er_findresident(REG(a1,STRPTR name)) {
- struct Resident *ret = NULL;
- STRPTR s1, s2;
-
- if (glob_ss) {
- er_lock();
- while ( (ret = er_nextresident(ret)) ) {
- for ( s1 = name, s2 = ret->rt_Name; *s1 && (*s1 == *s2) ; s1++, s2++ );
- if (*s1 == *s2) {
- er_unlock();
- return ret;
- }
- }
- er_unlock();
- }
-
- return NULL;
- }
-